using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.RecipeFramework;
using EnvDTE;
using Microsoft.Practices.RecipeFramework.Library;
using System.ComponentModel.Design;
using Microsoft.Practices.ComponentModel;
using Microsoft.Practices.Common;
using System.Reflection;
using Microsoft.Practices.RecipeFramework.Services;
using System.Collections.Specialized;

namespace VSSDKAssist.Assets.ValueProviders.Base
{
	/// <summary>
	/// Base ValueProvider class.
	/// </summary>
	public abstract class ValueProviderBase : ValueProvider, IAttributesConfigurable
	{
		#region Fields
		DTE visualStudio;
		IDictionaryService dictionaryService;
		private ExpressionEvaluationService evaluator = new ExpressionEvaluationService();
		#endregion

		#region Properties
		/// <summary>
		/// Gets the visual studio.
		/// </summary>
		/// <value>The visual studio.</value>
		protected DTE VisualStudio
		{
			get
			{
				return this.visualStudio;
			}
		}

		/// <summary>
		/// Gets the dictionary service.
		/// </summary>
		/// <value>The dictionary service.</value>
		protected IDictionaryService DictionaryService
		{
			get
			{
				return this.dictionaryService;
			}
		}

		private Stage executionStage;

		/// <summary>
		/// The value provider execution stage.
		/// </summary>
		protected Stage ExecutionStage
		{
			get { return executionStage; }
			set { executionStage = value; }
		}

		#endregion

		#region Protected Implementation
		/// <summary>
		/// Called when [sited].
		/// </summary>
		protected override void OnSited()
		{
			base.OnSited();
			visualStudio = this.GetService<DTE>();
			dictionaryService = this.GetService<IDictionaryService>();
		}

		/// <summary>
		/// Evaluates the specified expression.
		/// </summary>
		/// <param name="expression">The expression.</param>
		/// <returns></returns>
		protected object Evaluate(String expression)
		{
			if(!String.IsNullOrEmpty(expression))
			{
				return this.evaluator.Evaluate(expression, new ServiceAdapterDictionary(dictionaryService)).ToString();
			}
			return expression;
		}

		private string packageBasePath;

		/// <summary>
		/// Gets the package base path.
		/// </summary>
		/// <value>The package base path.</value>
		protected virtual string PackageBasePath
		{
			get
			{
				if(string.IsNullOrEmpty(packageBasePath))
				{
					IConfigurationService configService = this.GetService<IConfigurationService>();
					packageBasePath = configService.BasePath;
				}

				return packageBasePath;
			}
		}

		/// <summary>
		/// Called when [configure].
		/// </summary>
		/// <param name="attributes">The attributes.</param>
		protected virtual void OnConfigure(StringDictionary attributes)
		{
		}
		#endregion

		#region IAttributesConfigurable Members

		/// <summary>
		/// Configures the component using the dictionary of attributes specified
		/// in the configuration file.
		/// </summary>
		/// <param name="attributes">The attributes in the configuration element.</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
		public void Configure(StringDictionary attributes)
		{
			if(attributes.ContainsKey("Stage"))
			{
				this.ExecutionStage = (Stage)Enum.Parse(typeof(Stage), attributes["Stage"]);
			}

			OnConfigure(attributes);
		}
		#endregion

		/// <summary>
		/// Enum to represent a value provider execution stage
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32")]
		public enum Stage : byte
		{
			/// <summary>
			/// All
			/// </summary>
			All = 0,
			/// <summary>
			/// OnBeforeActions
			/// </summary>
			OnBeforeActions = 2,
			/// <summary>
			/// OnBeginRecipe
			/// </summary>
			OnBeginRecipe = 1
		}
	}
}